use std::collections::BTreeMap;
use serde::Deserialize;
use rust_decimal::Decimal;
use crate::errors::BinanceError;
use crate::ws::DepthUpdate;

#[derive(Debug, Clone, Deserialize)]
pub struct DepthLevel {
    pub price: Decimal,
    pub qty: Decimal,
}

/// 订单簿

/// 订单簿 Raw 结构体
#[derive(Debug, Deserialize)]
pub struct OrderBookRaw {
    #[serde(rename = "lastUpdateId")]
    pub last_update_id: u64,
    pub bids: Vec<[String; 2]>,
    pub asks: Vec<[String; 2]>,
}

impl OrderBookRaw {

    fn vec_to_btreemap(&self, levels: &[[String; 2]]) -> Option<BTreeMap<Decimal, Decimal>> {
        Some(
            levels.iter()
                .filter_map(|[price, qty]| {
                    let p = Decimal::from_str_exact(price).ok()?;
                    let q = Decimal::from_str_exact(qty).ok()?;
                    Some((p, q))
                })
                .collect::<BTreeMap<Decimal, Decimal>>()
        )
    }
    pub fn to_model(&self) -> Option<OrderBook> {
        // 转换 bids 和 asks Vec<[String; 2]> -> BTreeMap<Decimal, Decimal>
        let bids_map: Option<BTreeMap<Decimal, Decimal>> = self.vec_to_btreemap(&self.bids);
        let asks_map: Option<BTreeMap<Decimal, Decimal>> = self.vec_to_btreemap(&self.asks);

        Some(OrderBook {
            symbol: "".into(),
            last_update_id: self.last_update_id,
            bids: bids_map?,
            asks: asks_map?,
        })
    }
}

#[derive(Debug, Clone, Deserialize)]
pub struct OrderBook {
    pub symbol: String,
    pub last_update_id: u64,
    pub bids: BTreeMap<Decimal, Decimal>, // 升序存储，最高买价在末尾
    pub asks: BTreeMap<Decimal, Decimal>, // 升序存储，最低卖价在开头
}

impl OrderBook {
    pub fn new() -> Self {
        Self {
            symbol: "".into(),
            last_update_id: 0,
            bids: BTreeMap::new(),
            asks: BTreeMap::new(),
        }
    }
    pub fn new_with_symbol(symbol: String) -> Self {
        Self {
            symbol,
            last_update_id: 0,
            bids: BTreeMap::new(),
            asks: BTreeMap::new(),
        }
    }

    pub fn apply_whole_orderbook(&mut self, whole_orderbook: &OrderBook) {
        self.bids.clear();
        self.asks.clear();
        self.bids.extend(whole_orderbook.bids.iter().map(|(p, q)| (*p, *q)));
        self.asks.extend(whole_orderbook.asks.iter().map(|(p, q)| (*p, *q)));
    }

    pub fn apply_depth_update(&mut self, depth_update: DepthUpdate) -> Result<(), BinanceError> {
        // 先做消息连续性检查
        if depth_update.first_update_id > self.last_update_id + 1 {
            return Err(BinanceError::Other(format!(
                "Gap detected: local last_update_id {}, depth_update first_update_id {}",
                self.last_update_id, depth_update.first_update_id
            )));
        }

        if depth_update.final_update_id <= self.last_update_id {
            return Err(BinanceError::Other(format!(
                "Outdated update: local last_update_id {}, depth_update final_update_id {}",
                self.last_update_id, depth_update.final_update_id
            )));
        }

        for bid in depth_update.bids.iter() {
            if bid.qty.is_zero() {
                self.bids.remove(&bid.price);
            } else {
                self.bids.insert(bid.price, bid.qty);
            }
        }
        for ask in depth_update.asks.iter() {
            if ask.qty.is_zero() {
                self.asks.remove(&ask.price);
            } else {
                self.asks.insert(ask.price, ask.qty);
            }
        }

        Ok(())
    }

    pub fn apply_depth_update_with_vec(&mut self, bids_update: &[(Decimal, Decimal)], asks_update: &[(Decimal, Decimal)]) {
        for (price, qty) in bids_update {
            if qty.is_zero() {
                self.bids.remove(price);
            } else {
                self.bids.insert(*price, *qty);
            }
        }
        for (price, qty) in asks_update {
            if qty.is_zero() {
                self.asks.remove(price);
            } else {
                self.asks.insert(*price, *qty);
            }
        }
    }

    // 返回买盘第 i 档（i 从 0 开始），按价格从高到低
    pub fn get_bid(&self, index: usize) -> Option<(Decimal, Decimal)> {
        self.bids.iter().rev().nth(index).map(|(price, qty)| (*price, *qty))
    }

    // 返回卖盘第 i 档（i 从 0 开始），按价格从低到高
    pub fn get_ask(&self, index: usize) -> Option<(Decimal, Decimal)> {
        self.asks.iter().nth(index).map(|(price, qty)| (*price, *qty))
    }

    // 可选：转成Vec方便批量操作
    pub fn bids_as_vec(&self) -> Vec<(Decimal, Decimal)> {
        self.bids.iter().rev().map(|(p, q)| (*p, *q)).collect()
    }

    pub fn asks_as_vec(&self) -> Vec<(Decimal, Decimal)> {
        self.asks.iter().map(|(p, q)| (*p, *q)).collect()
    }

    pub fn dump(&self, title: &str, levels: usize) {
        println!("------ {} OrderBook Dump (Top {} Levels) ------", title, levels);

        // 买盘：BTreeMap 默认是升序，这里需要反向迭代，价格最高档在前
        let bids_top: Vec<_> = self.bids.iter().rev().take(levels).collect();
        // 卖盘：价格升序，直接take levels
        let asks_top: Vec<_> = self.asks.iter().take(levels).collect();

        println!("{:<20} | {:<20} || {:<20} | {:<20}",
                 "Bid Price", "Bid Qty", "Ask Price", "Ask Qty");
        println!("{}", "-".repeat(88));

        // 取买卖档位最大数量，避免索引越界
        let max_len = bids_top.len().max(asks_top.len());

        for i in 0..max_len {
            let bid = bids_top.get(i).map(|(p,q)| (p, q));
            let ask = asks_top.get(i).map(|(p,q)| (p, q));

            // 格式化输出，价格和数量用字符串，方便阅读
            let bid_str = if let Some((price, qty)) = bid {
                format!("{:>18} {:>18}", price.normalize(), qty.normalize())
            } else {
                " ".repeat(37)
            };

            let ask_str = if let Some((price, qty)) = ask {
                format!("{:>18} {:>18}", price.normalize(), qty.normalize())
            } else {
                "".to_string()
            };

            println!("{} || {}", bid_str, ask_str);
        }
    }
}

/// 交易所资产信息 Raw
#[derive(Debug, Deserialize)]
pub struct AssetRaw {
    pub asset: String,
    #[serde(rename = "marginAvailable")]
    pub margin_available: bool,
    #[serde(rename = "autoAssetExchange")]
    pub auto_asset_exchange: Option<String>, // 可能为字符串数字或null
}

impl AssetRaw {
    pub fn to_model(&self) -> Asset {
        Asset {
            asset: self.asset.clone(),
            margin_available: self.margin_available,
            auto_asset_exchange: self.auto_asset_exchange
                .as_ref()
                .and_then(|s| s.parse::<i32>().ok()),
        }
    }
}

/// 交易所资产信息
#[derive(Debug, Clone)]
pub struct Asset {
    pub asset: String,
    pub margin_available: bool,
    pub auto_asset_exchange: Option<i32>,
}

/// 合约交易规则过滤器 Raw，区分多种 filterType
#[derive(Debug, Deserialize, Clone)]
#[serde(tag = "filterType")]
pub enum SymbolFilterRaw {
    PRICE_FILTER {
        maxPrice: String,
        minPrice: String,
        tickSize: String,
    },
    LOT_SIZE {
        maxQty: String,
        minQty: String,
        stepSize: String,
    },
    MARKET_LOT_SIZE {
        maxQty: String,
        minQty: String,
        stepSize: String,
    },
    MAX_NUM_ORDERS {
        limit: u32, // JSON中数字作为字符串处理
    },
    MAX_NUM_ALGO_ORDERS {
        limit: u32,
    },
    MIN_NOTIONAL {
        notional: String,
    },
    PERCENT_PRICE {
        multiplierUp: String,
        multiplierDown: String,
        multiplierDecimal: String, // 注意这里是字符串数字
    },
    // 其他可能存在的 filter 类型
    #[serde(other)]
    Unknown,
}

/// 合约交易对信息 Raw
#[derive(Debug, Deserialize, Clone)]
pub struct SymbolRaw {
    pub symbol: String,
    pub pair: String,
    #[serde(rename = "contractType")]
    pub contract_type: String,
    pub deliveryDate: u64,
    pub onboardDate: u64,
    pub status: String,
    pub maintMarginPercent: String,
    pub requiredMarginPercent: String,
    pub baseAsset: String,
    pub quoteAsset: String,
    pub marginAsset: String,
    pub pricePrecision: u32,
    pub quantityPrecision: u32,
    pub baseAssetPrecision: u32,
    pub quotePrecision: u32,
    pub underlyingType: String,
    pub underlyingSubType: Option<Vec<String>>,
    pub triggerProtect: String,
    pub filters: Vec<SymbolFilterRaw>,
    #[serde(rename = "orderTypes")]
    pub order_types: Vec<String>,
    pub timeInForce: Vec<String>,
    pub liquidationFee: String,
    pub marketTakeBound: String,
}

/// 交易所信息 Raw
#[derive(Debug, Deserialize)]
pub struct ExchangeInfoRaw {
    pub exchangeFilters: Vec<serde_json::Value>,
    pub rateLimits: Vec<serde_json::Value>,
    pub serverTime: u64,
    pub assets: Vec<AssetRaw>,
    pub symbols: Vec<SymbolRaw>,
    pub timezone: String,
}

impl ExchangeInfoRaw {
    pub fn to_model(self) -> ExchangeInfo {
        ExchangeInfo {
            exchange_filters: self.exchangeFilters,
            rate_limits: self.rateLimits,
            server_time: self.serverTime,
            assets: self.assets.into_iter().map(|a| a.to_model()).collect(),
            symbols: self.symbols, // 这里为了简化，直接用原始结构
            timezone: self.timezone,
        }
    }
}

/// 交易所信息业务结构
#[derive(Debug, Clone)]
pub struct ExchangeInfo {
    pub exchange_filters: Vec<serde_json::Value>,
    pub rate_limits: Vec<serde_json::Value>,
    pub server_time: u64,
    pub assets: Vec<Asset>,
    pub symbols: Vec<SymbolRaw>,
    pub timezone: String,
}

impl ExchangeInfo {
    pub fn get_trading_symbols(&self) -> Vec<String> {
        self.symbols.iter()
        .filter(|s| s.status == "TRADING")
        .map(|s| s.symbol.clone()).collect()
    }
}
